#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int maxv = 510;
const int INF = 0x3FFFFFFF;
int n,m,c1,c2;      //n为城市总数，m为路径数，c1为起点，c2为终点
int G[maxv][maxv];  //用邻接矩阵表示图
int num[maxv];      //num[i]表示ith城所拥有的救火队数
int numS[maxv];     //目前numS[i]表示从起点到ith城得最短路径条数
int totTeam[maxv];  //totTeam[i]表示从起点出发到ith城当前最短路径上所能聚集的最大队伍数
int d[maxv];        //d[i]表示起点到ith城已知的最短距离
bool visited[maxv];  //visited[i]为true表明ith城已经访问，从起点到ith城的最短路径是确定的
void Dijkstra(int start, int end)
{
    fill(numS,numS+maxv,0);
    fill(d,d+maxv,INF);
    fill(totTeam,totTeam,0);
    fill(visited,visited+maxv,false);
    d[start] = 0;
    numS[start] = 1;
    totTeam[start] = num[start];
    while(true) {
        //寻找未访问过且距起始点最近的点
        int minD = INF,u = -1;
        for(int i = 0; i < n; i++) {
            if(visited[i]==false&&d[i]<minD) {
                minD = d[i];
                u = i;
            }
        }
        if(u==-1||u==end) return;
        visited[u] = true;
        for(int i = 0; i < n; i++) {
            //以u为中介更新与u相连的点的参数
            if(visited[i]==false&&G[u][i]!=INF) {//只有未访问过的点才会进行更新
                if(d[u]+G[u][i]<d[i]) {
                    //以u为中介从起点到i更近
                    d[i] = d[u]+G[u][i];
                    numS[i] = numS[u];
                    totTeam[i] = totTeam[u]+num[i];
                }
                else if(d[u]+G[u][i]==d[i]){
                    numS[i] += numS[u];
                    totTeam[i] = std::max(totTeam[i],totTeam[u]+num[i]);
                }
            }
        }
    }
}


int main(void)
{
    cin>>n>>m>>c1>>c2;
    fill(G[0],G[0]+maxv*maxv,INF);
    for(int i = 0; i < n; i++) {
        cin>>num[i];
    }
    for(int i = 0; i<m;i++) {
        int tempC1,tempC2;
        cin>>tempC1>>tempC2;
        cin>>G[tempC1][tempC2];
        G[tempC2][tempC1] = G[tempC1][tempC2];
    }
    Dijkstra(c1,c2);
    printf("%d %d\n",numS[c2],totTeam[c2]);
    return 0;
}






















/*
// PATA 1003.cpp : 定义控制台应用程序的入口点。
//
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXV = 510;
const int INF = 0x3fffffff;
int G[MAXV][MAXV];
bool vis[MAXV] = { false };
int totTeam[MAXV] = {0};//从指定起点沿路径集合的队伍
int team[MAXV];//每个城市队伍数
int num[MAXV];//从指定起点到i的最短路径数
int d[MAXV];
int n, m, c1, c2;//城市数，道路数，起点，终点

void Dijkstra(int start, int end)
{
	fill(d, d + MAXV, INF);
	num[start] = 1;
	totTeam[start] = team[start];
	d[start] = 0;
	for (int i = 0;i < n;i++) {
		int MIN = INF, u = -1;
		for (int j = 0;j < n;j++) {
			//选取d[j]未访问过的最小的点
			if (vis[j] == false && d[j] < MIN) {
				MIN = d[j];
				u = j;
			}
		}
		vis[u] = true;
		if (u == c2 || u == -1) return;
		for (int j = 0;j < n;j++) {
			//将能通过中介u获得起点到点j的最短路径进行更新，点j未访问，u可到达j,
			if (vis[j] == false && G[u][j] != INF) {
				if (d[u] + G[u][j] < d[j]) {
					d[j] = d[u] + G[u][j];
					num[j] = num[u];
					totTeam[j] = totTeam[u] + team[j];
				}
				else if (d[u] + G[u][j] == d[j]) {//最短距离相同时可以更新num[j]
					num[j] += num[u];
					if (totTeam[u] + team[j] > totTeam[j]) {
						totTeam[j] = totTeam[u] + team[j];//更新总救援队数目
					}
				}
			}	
		}
	}
}
int main()
{
	scanf("%d%d%d%d", &n, &m, &c1, &c2);
	int teamnum;
	fill(G[0], G[0] + MAXV*MAXV, INF);
	for (int i = 0;i < n;i++) {
		scanf("%d", &teamnum);
		team[i] = teamnum;
	}
	for (int i = 0;i < m;i++) {
		int v1, v2, len;
		scanf("%d%d%d", &v1, &v2, &len);
		G[v1][v2] = G[v2][v1] = len;
	}
	Dijkstra(c1,c2);
	printf("%d %d\n", num[c2], totTeam[c2]);

    return 0;
}
*/